module sdldee.init;

import std.string;
import std.stdio;
import std.gc;

import sdldee.c.sdl;
import sdldee.exception;


/**
 * Flags to be passed to Init specifying which subsystems
 * to initialise.
 */
enum InitFlag {
	TIMER = 0x00000001, /// Initialise the timer subsystem.
	AUDIO = 0x00000010, /// Initialise the audio subsystem.
	VIDEO = 0x00000020, /// Initialise the video subsystem.
	CDROM = 0x00000100, /// Initialise the CD-ROM subsystem.
	JOYSTICK = 0x00000200, /// Initialise the joystick subsystem.
	NOPARACHUTE = 0x00100000, /// Prevent SDL from catching fatal signals. 
	EVENTTHREAD = 0x01000000, /// Run the event manager in a seperate thread.
	EVERYTHING = 0x0000FFFF /// Initialise all subsystems.
}

/**
 * Initialise SDL.
 *
 * Initialise SDL. This should be called before using any other SDL functions.
 *
 * Throws: InitException on failure.
 *
 * Params:
 *  flags = Specifies which subsystems to initialise, as bitwise-ORed members of InitFlag.
 *          Default is to initialise all subsystems.
 *
 * See_Also: Quit, InitSubSystem, InitException
 */
void init(uint flags = InitFlag.EVERYTHING) {
	debug {
		writefln("Initialising SDL:");
		if(flags & InitFlag.EVERYTHING)
			writefln("All subsystems");
		else {
			if(flags & InitFlag.TIMER)
				writefln("Timer subsystem");
			if(flags & InitFlag.AUDIO)
				writefln("Audio subsystem");
			if(flags & InitFlag.VIDEO)
				writefln("Video subsystem");
			if(flags & InitFlag.CDROM)
				writefln("CD-ROM subsystem");
			if(flags & InitFlag.JOYSTICK)
				writefln("Joystick subsystem");
		}
		if(flags & InitFlag.NOPARACHUTE)
			writefln("SDL will not catch fatal signals.");
		if(flags & InitFlag.EVENTTHREAD)
			writefln("Event manager will run in seperate thread");
		writefln();
	}
	if(SDL_Init(flags) != 0)
		throw new SdlException("Error initialising SDL");
}

/**
 * Initialise additional SDL subsystems.
 *
 * Initialise additional SDL subsystems after SDL has already been initialised with Init.
 *
 * Throws: InitException on failure.
 *
 * Params:
 *  flags = Specifies which subsystems to initialise, as bitwise-ORed members of InitFlag.
 *
 * See_Also: Init, Quit, QuitSubSystem, InitException
 */
void initSubSystem(uint flags) {
	debug {
		writefln("Initialising SDL subsystems:", flags);
		if(flags & InitFlag.EVERYTHING)
			writefln("All subsystems");
		else {
			if(flags & InitFlag.TIMER)
				writefln("Timer subsystem");
			if(flags & InitFlag.AUDIO)
				writefln("Audio subsystem");
			if(flags & InitFlag.VIDEO)
				writefln("Video subsystem");
			if(flags & InitFlag.CDROM)
				writefln("CD-ROM subsystem");
			if(flags & InitFlag.JOYSTICK)
				writefln("Joystick subsystem");
		}
		writefln();
	}
	if(SDL_InitSubSystem(flags) != 0)
		throw new SdlException("Unable to initiliase subsystem");
}

/**
 * Shut down a subsystem.
 *
 * Shut down a subsystem that was previously initialised with init or initSubSystem.
 *
 * Params:
 *  flags = Specifies which subsystems to shutdown, as bitwise-ORed members of InitFlag.
 *
 * See_Also: Init, InitSubSystem, Quit
 */
void quitSubSystem(uint flags) {
	debug {
		writefln("Shutting down SDL subsystems:");
		if(flags & InitFlag.EVERYTHING)
			writefln("All subsystems");
		else {
			if(flags & InitFlag.TIMER)
				writefln("Timer subsystem");
			if(flags & InitFlag.AUDIO)
				writefln("Audio subsystem");
			if(flags & InitFlag.VIDEO)
				writefln("Video subsystem");
			if(flags & InitFlag.CDROM)
				writefln("CD-ROM subsystem");
			if(flags & InitFlag.JOYSTICK)
				writefln("Joystick subsystem");
		}
		writefln();
	}
	SDL_QuitSubSystem(flags);
}

/**
 * Checks which subsystems are initialized
 *
 * Allows you to see which SDL subsytems have been initialized.
 *
 * Params:
 *  flags = Specifies which subsystems to check, as bitwise-ORed members of InitFlag.
 *           If flags is 0, then all subsystems are checked.
 *
 * Returns: A bitwised OR'd combination of members of InitFlag of the initialized subsystems.

/**
 * Shut down SDL.
 *
 * Shuts down all SDL subsystems and frees the resources allocated to them.
 * This should always be called before you exit.
 *
 * See_Also: QuitSubSystem, Init
 */
void quit() {
	debug {
		writefln("Shutting down SDL");
		writefln();
	}
	SDL_Quit();
}

